﻿Imports System.ComponentModel
Imports System.Text

Public Class LabContact
    Implements INotifyPropertyChanged
    Implements IDataErrorInfo

#Region " Declarations "

    Private _datBirthday As Nullable(Of Date)
    Private _intNumberOfComputers As Integer
    Private _objErrors As IDictionary(Of String, String)
    Private _strFirstName As String = String.Empty
    Private _strLastName As String = String.Empty

#End Region

#Region " Events "

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

#End Region

#Region " Properties "

    Public Property Birthday() As Nullable(Of Date)
        Get
            Return _datBirthday
        End Get
        Set(ByVal Value As Nullable(Of Date))

            If Not _datBirthday.HasValue AndAlso Not Value.HasValue Then
                'both are Nothing
                Exit Property
            ElseIf _datBirthday.HasValue AndAlso Value.HasValue AndAlso _datBirthday.Value = Value.Value Then
                'both have values and are equal
                Exit Property
            End If

            _datBirthday = Value
            OnPropertyChanged("Birthday")
        End Set
    End Property

    Public ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.Error
        Get
            If Me.Errors.Count > 0 Then
                Dim sb As New StringBuilder(1024)
                For Each kvp As KeyValuePair(Of String, String) In Me.Errors
                    sb.AppendLine(kvp.Value)
                Next
                Return sb.ToString
            Else
                Return String.Empty
            End If

        End Get
    End Property

    Public ReadOnly Property Errors() As IDictionary(Of String, String)
        Get
            Return _objErrors
        End Get
    End Property

    Public Property FirstName() As String
        Get
            Return _strFirstName
        End Get
        Set(ByVal Value As String)
            If _strFirstName <> Value Then
                _strFirstName = Value
                OnPropertyChanged("FirstName")
            End If
        End Set
    End Property

    Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
        Get
            Dim strError As String = String.Empty
            Me.Errors.Remove(columnName)

            Select Case columnName
                Case "Birthday"
                    If Me.Birthday.HasValue AndAlso Me.Birthday > Today Then
                        strError = "Birthday must be before today."
                    End If
                Case "NumberOfComputers"
                    If Me.NumberOfComputers < 0 Then
                        strError = "Number of computers must be greater than or equal to zero."
                    End If
                Case "FirstName"
                    If String.IsNullOrEmpty(Me.FirstName.Trim) Then
                        strError = "First name is a required field."
                    End If
                Case "LastName"
                    If String.IsNullOrEmpty(Me.LastName.Trim) Then
                        strError = "Last name is a required field."
                    End If
            End Select

            If Not String.IsNullOrEmpty(strError) Then
                Me.Errors.Add(columnName, strError)

            End If
            Return strError
        End Get
    End Property

    Public Property LastName() As String
        Get
            Return _strLastName
        End Get
        Set(ByVal Value As String)
            If _strLastName <> Value Then
                _strLastName = Value
                OnPropertyChanged("LastName")
            End If
        End Set
    End Property

    Public Property NumberOfComputers() As Integer
        Get
            Return _intNumberOfComputers
        End Get
        Set(ByVal Value As Integer)
            If _intNumberOfComputers <> Value Then
                _intNumberOfComputers = Value
                OnPropertyChanged("NumberOfComputers")
            End If
        End Set
    End Property

#End Region

#Region " Constructors "

    Public Sub New()
        _objErrors = New Dictionary(Of String, String)
    End Sub

#End Region

#Region " Methods "

    Protected Sub OnPropertyChanged(ByVal strPropertyName As String)

        If Me.PropertyChangedEvent IsNot Nothing Then

            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(strPropertyName))

        End If
    End Sub

#End Region

End Class
